<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no,initial-scale=1.0"/>
    <title>three</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            overflow: hidden;
            color: white;
            font-family: Courier New, Courier, monospace;
        }

        *, *::before, *::after {
            box-sizing: border-box;
        }

        .GUI {
            width: 100%;
            height: 100%;
            position: fixed;
            top: 0;
            left: 0;
        }

        .score {
            position: absolute;
            top: 60px;
            left: 30px;
            font-size: 2rem;
        }

        .instructions {
            position: absolute;
            top: 30px;
            left: 30px;
        }

        .overlay-wrapper {
            visibility: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
            width: 100%;
            height: 100%;
            position: absolute;
            top: 0;
            left: 0;
        }

        .overlay {
            display: flex;
            flex-direction: column;
            padding: 40px;
            background-color: rgba(0, 0, 0, .3);
            border: 3px solid rgba(0, 0, 0, .2);
            text-align: center;
        }

        .overlay-title {
            margin: 0;
            position: relative;
            text-transform: uppercase;
            font-size: 4rem;
            line-height: 1;
            font-weight: 300;
            mix-blend-mode: screen;
        }

        .overlay-title::before {
            content: "Game Over";
            position: absolute;
            font-weight: 700;
            background-image: linear-gradient(to bottom, #00ffff 0%, #ff00ff 100%);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            filter: blur(3px);
            z-index: -1;
            text-shadow: none;
        }

        .overlay-score {
            margin: 30px 0;
            font-size: 1.6rem;
            text-shadow: 0 0 12px rgba(0, 255, 255, .8);
        }

        .overlay-button {
            margin: 0 auto;
            padding: 15px 30px;
            border: 3px solid white;
            position: relative;
            text-shadow: 0 0 12px rgba(0, 255, 255, .8);
            appearance: none;
            cursor: pointer;
            outline: none;
            background-color: transparent;
            color: white;
            font-family: Courier New, Courier, monospace;
            font-size: 1.6rem;
        }

        .overlay-button::before {
            content: "";
            display: block;
            width: calc(100% + 6px);
            height: calc(100% + 6px);
            border: 3px solid white;
            border-image: linear-gradient(to bottom, #00ffff 0%, #ff00ff 100%) 10;
            position: absolute;
            top: -3px;
            left: -3px;
            z-index: -1;
            transition-duration: 200ms;
            transition-property: filter, border-width, top, left, width, height;
        }

        .overlay-button:hover::before {
            border-width: 9px;
            filter: blur(2px);
            top: -6px;
            left: -6px;
            width: calc(100% + 12px);
            height: calc(100% + 12px);
        }
    </style>
</head>
<body>
<div class="GUI">
    <div class="score">成绩: <output class="score-amount js-score">0</span></output></div>
    <div class="instructions">使用 A/D 或者 左右方向键 控制移动</div>
    <div id="gameover" class="overlay-wrapper">
        <div class="overlay">
            <h2 class="overlay-title">Game Over</h2>
            <div class="overlay-score">成绩: <output class="score-amount js-score">0</output></div>
            <button class="overlay-button js-play">重新开始</button>
        </div>
    </div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r79/three.min.js"></script>
<script>
    const spaceshipModel = {
        "uvs": [[0.27906113862991333, 0.33436039090156555, 0.3161470592021942, 0.33436039090156555, 0.2734621465206146, 0.25258663296699524, 0.2734621465206146, 0.15861955285072327, 0.3217460811138153, 0.15861955285072327, 0.3217460811138153, 0.25258663296699524, 0.3105480968952179, 0.41613414883613586, 0.2846601903438568, 0.41613414883613586, 0.23932033777236938, 0.25258663296699524, 0.23932033777236938, 0.18672767281532288, 0.273462176322937, 0.12086869776248932, 0.3217460811138153, 0.12086869776248932, 0.35588791966438293, 0.25258663296699524, 0.35588791966438293, 0.18672767281532288, 0.2528374493122101, 0.33436039090156555, 0.34237074851989746, 0.33436039090156555, 0.3288535475730896, 0.41613414883613586, 0.26635462045669556, 0.41613414883613586, 0.23932033777236938, 0.12086869776248932, 0.2839176058769226, 0.08367034792900085, 0.3112906217575073, 0.08367034792900085, 0.35588791966438293, 0.12086869776248932, 0.2645619511604309, 0.08367034792900085, 0.3306463062763214, 0.08367034792900085, 0.58144611120224, 0.4954613745212555, 0.5310850739479065, 0.4954613745212555, 0.5310850739479065, 0.43834176659584045, 0.58144611120224, 0.43834176659584045, 0.5665895342826843, 0.5510128736495972, 0.5459415316581726, 0.5510128736495972, 0.5310850739479065, 0.38122227787971497, 0.58144611120224, 0.38122227787971497, 0.39441484212875366, 0.24721792340278625, 0.44269871711730957, 0.24721792340278625, 0.44269871711730957, 0.31307685375213623, 0.39441484212875366, 0.31307685375213623, 0.40001386404037476, 0.16544413566589355, 0.43709972500801086, 0.16544413566589355, 0.476840615272522, 0.24721792340278625, 0.476840615272522, 0.31307685375213623, 0.44269871711730957, 0.378935843706131, 0.39441484212875366, 0.378935843706131, 0.36027300357818604, 0.24721792340278625, 0.36027300357818604, 0.31307685375213623, 0.3737901449203491, 0.16544413566589355, 0.40561285614967346, 0.08367034792900085, 0.43150076270103455, 0.08367034792900085, 0.4633234441280365, 0.16544413566589355, 0.476840615272522, 0.378935843706131, 0.43224331736564636, 0.41613414883613586, 0.40487030148506165, 0.41613414883613586, 0.36027300357818604, 0.378935843706131, 0.387307345867157, 0.08367034792900085, 0.44980621337890625, 0.08367034792900085, 0.4515989422798157, 0.41613414883613586, 0.38551464676856995, 0.41613414883613586, 0.5859230756759644, 0.1392219066619873, 0.6362841129302979, 0.1392219066619873, 0.6362841129302979, 0.19634142518043518, 0.5859230756759644, 0.19634142518043518, 0.6007795333862305, 0.08367037773132324, 0.6214274764060974, 0.08367037773132324, 0.6362841129302979, 0.25346091389656067, 0.5859230756759644, 0.25346091389656067, 0.5277184844017029, 0.4935545027256012, 0.5089478492736816, 0.5137609839439392, 0.5089478492736816, 0.44477173686027527, 0.5277184844017029, 0.46497830748558044, 0.4824022650718689, 0.5137609839439392, 0.4824022650718689, 0.44477173686027527, 0.5198169350624084, 0.5401121377944946, 0.4715331494808197, 0.5401120185852051, 0.46363165974617004, 0.4935545027256012, 0.46363168954849243, 0.46497830748558044, 0.4715331196784973, 0.4184206426143646, 0.5198169350624084, 0.4184206426143646, 0.481118768453598, 0.21538829803466797, 0.5294026732444763, 0.21538829803466797, 0.5237872004508972, 0.2971620559692383, 0.4867341220378876, 0.2971620559692383, 0.49434319138526917, 0.19735026359558105, 0.5161781907081604, 0.19735026359558105, 0.5181718468666077, 0.378935843706131, 0.4923495352268219, 0.378935843706131, 0.481118768453598, 0.14952930808067322, 0.49434319138526917, 0.14952930808067322, 0.5294026732444763, 0.14952930808067322, 0.5161781907081604, 0.14952930808067322, 0.481118768453598, 0.08367037773132324, 0.49434319138526917, 0.10170841217041016, 0.5294026732444763, 0.08367037773132324, 0.5161781907081604, 0.10170841217041016, 0.5818047523498535, 0.24721792340278625, 0.5335209369659424, 0.24721792340278625, 0.5391363501548767, 0.16544416546821594, 0.5761893391609192, 0.16544416546821594, 0.5685803294181824, 0.26525595784187317, 0.5467453002929688, 0.26525595784187317, 0.5447517037391663, 0.08367037773132324, 0.5705740451812744, 0.08367037773132324, 0.5818047523498535, 0.3130768835544586, 0.5685803294181824, 0.3130768835544586, 0.5335209369659424, 0.3130768835544586, 0.5467453002929688, 0.3130768835544586, 0.5818047523498535, 0.378935843706131, 0.5685803294181824, 0.36089783906936646, 0.5335209369659424, 0.378935843706131, 0.5467453002929688, 0.36089783906936646, 0.4384301006793976, 0.4184206426143646, 0.46026504039764404, 0.4184206426143646, 0.4602651596069336, 0.5165088772773743, 0.4384301006793976, 0.5165088772773743, 0.343448668718338, 0.4184206426143646, 0.3892560601234436, 0.4184206426143646, 0.3892560601234436, 0.5165088772773743, 0.3642469644546509, 0.5165088772773743, 0.43506351113319397, 0.4184206426143646, 0.4142652750015259, 0.5165088772773743, 0.2942747175693512, 0.4184206426143646, 0.3400821089744568, 0.4184206426143646, 0.3192838728427887, 0.5165088772773743, 0.2942747175693512, 0.5165088772773743, 0.24846728146076202, 0.4184206426143646, 0.2692655026912689, 0.5165088772773743, 0.23932038247585297, 0.518795371055603, 0.2611554265022278, 0.518795371055603, 0.261155366897583, 0.6168836355209351, 0.23932033777236938, 0.6168837547302246, 0.2869286835193634, 0.6168837547302246, 0.2650936245918274, 0.6168837547302246, 0.2650936245918274, 0.518795371055603, 0.2869286835193634, 0.518795371055603, 0.40804117918014526, 0.6168836355209351, 0.3622337579727173, 0.6168836355209351, 0.3622337579727173, 0.518795371055603, 0.3872429132461548, 0.518795371055603, 0.31642627716064453, 0.6168836355209351, 0.3372245728969574, 0.518795371055603, 0.4574131667613983, 0.6404868364334106, 0.41160571575164795, 0.6404868364334106, 0.4324040114879608, 0.5423985719680786, 0.4574131667613983, 0.5423985719680786, 0.5032205581665039, 0.6404868364334106, 0.4824222922325134, 0.5423985719680786, 0.312595009803772, 0.6168836355209351, 0.29075998067855835, 0.6168836355209351, 0.2907600402832031, 0.518795371055603, 0.31259506940841675, 0.518795371055603, 0.6765620112419128, 0.17023292183876038, 0.6547271013259888, 0.17023292183876038, 0.6404640674591064, 0.1392219066619873, 0.6908251047134399, 0.1392219066619873, 0.6547271013259888, 0.19634142518043518, 0.6404640674591064, 0.19634142518043518, 0.6553205847740173, 0.08367037773132324, 0.6759685277938843, 0.08367037773132324, 0.6765620112419128, 0.19634142518043518, 0.6908251047134399, 0.19634142518043518, 0.6547271013259888, 0.2224498689174652, 0.6404640674591064, 0.25346091389656067, 0.6765620112419128, 0.2224498689174652, 0.6908251047134399, 0.25346091389656067, 0.6995301842689514, 0.33897534012794495, 0.7213651537895203, 0.33897534012794495, 0.7356281876564026, 0.3699863851070404, 0.6852671504020691, 0.3699863851070404, 0.7213651537895203, 0.3128668963909149, 0.7356281876564026, 0.3128668963909149, 0.7207716107368469, 0.42553797364234924, 0.7001236081123352, 0.42553797364234924, 0.6995301842689514, 0.3128668963909149, 0.6852671504020691, 0.3128668963909149, 0.7213651537895203, 0.2867583930492401, 0.7356281876564026, 0.25574734807014465, 0.6995301842689514, 0.2867583930492401, 0.6852671504020691, 0.25574734807014465, 0.6928291916847229, 0.4278244078159332, 0.6928291916847229, 0.44938012957572937, 0.673616349697113, 0.44938012957572937, 0.673616349697113, 0.4278245270252228, 0.6819005012512207, 0.3112989366054535, 0.6819005012512207, 0.368418425321579, 0.6350399255752563, 0.368418425321579, 0.6350399255752563, 0.3112989366054535, 0.6819005012512207, 0.42553797364234924, 0.6350399255752563, 0.42553797364234924, 0.6488637924194336, 0.25574734807014465, 0.6680766344070435, 0.25574734807014465, 0.7418656945228577, 0.14078986644744873, 0.7418656945228577, 0.19790935516357422, 0.6950049996376038, 0.19790935516357422, 0.6950049996376038, 0.14078986644744873, 0.7280418872833252, 0.25346091389656067, 0.7088289260864258, 0.25346091389656067, 0.7418656945228577, 0.08367034792900085, 0.6950049996376038, 0.08367034792900085, 0.6702137589454651, 0.4278244078159332, 0.6702137589454651, 0.48039916157722473, 0.623353123664856, 0.48039916157722473, 0.623353123664856, 0.42782434821128845, 0.6971439123153687, 0.4493800699710846, 0.6971439123153687, 0.4278244078159332, 0.7163567543029785, 0.4278244078159332, 0.7163568139076233, 0.4493800699710846, 0.7389947772026062, 0.369986355304718, 0.7389947772026062, 0.31286686658859253, 0.7858554124832153, 0.31286686658859253, 0.7858554124832153, 0.369986355304718, 0.7389947772026062, 0.25574734807014465, 0.7858554124832153, 0.25574734807014465, 0.7720314860343933, 0.4255378544330597, 0.7528187036514282, 0.4255378544330597, 0.5848127603530884, 0.368418425321579, 0.5848127603530884, 0.3112989366054535, 0.6316733360290527, 0.3112989366054535, 0.6316733360290527, 0.368418425321579, 0.5986365079879761, 0.25574734807014465, 0.6178493499755859, 0.25574734807014465, 0.5848127603530884, 0.42553797364234924, 0.6316733360290527, 0.42553797364234924, 0.5730898380279541, 0.6058740615844727, 0.5730898976325989, 0.5532993078231812, 0.619950532913208, 0.5532994270324707, 0.6199504733085632, 0.6058741807937622, 0.5067851543426514, 0.5994353294372559, 0.5067851543426514, 0.5724095106124878, 0.5250442624092102, 0.5532993078231812, 0.5250442624092102, 0.618545413017273, 0.5508666634559631, 0.5532993078231812, 0.5508666634559631, 0.618545413017273, 0.5691258311271667, 0.5724095106124878, 0.5691258311271667, 0.5994353294372559, 0.4800853729248047, 0.8318504095077515, 0.48004066944122314, 0.7808135747909546, 0.6538245677947998, 0.7793998122215271, 0.6538715362548828, 0.8330054879188538, 0.28433334827423096, 0.7643555402755737, 0.2844071686267853, 0.848599910736084, 0.47724205255508423, 0.7514933347702026, 0.6989283561706543, 0.7513282299041748, 0.6990244388580322, 0.8610098958015442, 0.4773380756378174, 0.8611749410629272]],
        "faces": [41, 48, 49, 50, 51, 232, 233, 234, 235, 0, 1, 2, 3, 41, 1, 2, 38, 39, 2, 8, 9, 3, 4, 5, 6, 7, 41, 88, 89, 90, 91, 24, 25, 26, 27, 8, 9, 10, 11, 41, 3, 4, 36, 37, 42, 32, 35, 43, 12, 13, 14, 15, 41, 4, 5, 35, 36, 32, 33, 34, 35, 16, 17, 18, 19, 41, 5, 6, 34, 35, 33, 38, 39, 34, 20, 21, 22, 23, 41, 94, 95, 96, 97, 56, 57, 58, 59, 24, 25, 26, 27, 41, 7, 0, 32, 33, 12, 5, 4, 13, 28, 29, 30, 31, 41, 8, 9, 17, 16, 11, 10, 19, 20, 32, 33, 34, 35, 41, 9, 10, 18, 17, 10, 18, 22, 19, 36, 37, 38, 39, 41, 10, 11, 19, 18, 70, 71, 68, 65, 40, 41, 42, 43, 41, 11, 12, 20, 19, 51, 41, 50, 55, 44, 45, 46, 47, 41, 12, 13, 21, 20, 41, 40, 49, 50, 48, 49, 50, 51, 41, 13, 14, 22, 21, 40, 48, 54, 49, 52, 53, 54, 55, 41, 14, 15, 23, 22, 74, 75, 66, 69, 56, 57, 58, 59, 41, 15, 8, 16, 23, 21, 11, 20, 23, 60, 61, 62, 63, 41, 17, 18, 23, 16, 64, 65, 66, 67, 64, 65, 66, 67, 41, 41, 49, 48, 40, 236, 233, 232, 237, 68, 1, 0, 69, 41, 2, 1, 41, 42, 8, 2, 0, 14, 5, 4, 70, 71, 41, 3, 2, 42, 43, 76, 77, 78, 79, 72, 73, 74, 75, 41, 4, 3, 43, 44, 32, 42, 44, 36, 13, 12, 76, 77, 41, 5, 4, 44, 45, 33, 32, 36, 37, 17, 16, 78, 79, 41, 6, 5, 45, 46, 38, 33, 37, 47, 21, 20, 80, 81, 41, 7, 6, 46, 47, 92, 93, 94, 95, 82, 83, 84, 85, 41, 0, 7, 47, 40, 5, 12, 15, 1, 29, 28, 86, 87, 41, 33, 32, 8, 15, 13, 4, 11, 21, 31, 30, 88, 89, 41, 97, 96, 98, 99, 59, 58, 62, 63, 27, 26, 90, 91, 41, 35, 34, 14, 13, 34, 39, 48, 40, 23, 22, 92, 93, 41, 36, 35, 13, 12, 35, 34, 40, 41, 19, 18, 94, 95, 41, 37, 36, 12, 11, 43, 35, 41, 51, 15, 14, 96, 97, 41, 91, 90, 92, 93, 27, 26, 30, 31, 11, 10, 98, 99, 41, 39, 38, 10, 9, 3, 9, 18, 10, 7, 6, 100, 101, 41, 32, 39, 9, 8, 4, 3, 10, 11, 102, 103, 104, 105, 41, 41, 40, 24, 25, 0, 1, 6, 7, 106, 107, 108, 109, 41, 42, 41, 25, 26, 14, 0, 7, 17, 71, 70, 110, 111, 41, 43, 42, 26, 27, 79, 78, 82, 83, 75, 74, 112, 113, 41, 44, 43, 27, 28, 36, 44, 52, 45, 77, 76, 114, 115, 41, 45, 44, 28, 29, 37, 36, 45, 46, 79, 78, 116, 117, 41, 46, 45, 29, 30, 47, 37, 46, 53, 81, 80, 118, 119, 41, 47, 46, 30, 31, 95, 94, 98, 99, 85, 84, 120, 121, 41, 40, 47, 31, 24, 1, 15, 16, 6, 87, 86, 122, 123, 41, 1, 39, 50, 49, 238, 239, 234, 233, 124, 125, 126, 127, 41, 39, 32, 51, 50, 239, 240, 235, 234, 128, 129, 130, 131, 41, 32, 0, 48, 51, 240, 241, 232, 235, 132, 133, 134, 135, 40, 0, 40, 48, 241, 237, 232, 133, 136, 134, 40, 41, 1, 49, 236, 238, 233, 137, 124, 127, 41, 2, 3, 53, 52, 77, 76, 80, 81, 73, 72, 138, 139, 41, 3, 37, 54, 53, 76, 84, 85, 80, 72, 140, 141, 138, 41, 38, 2, 52, 55, 86, 77, 81, 87, 142, 73, 139, 143, 41, 37, 11, 56, 54, 84, 88, 89, 85, 140, 144, 145, 141, 41, 11, 10, 57, 56, 88, 90, 91, 89, 144, 146, 147, 145, 41, 10, 38, 55, 57, 90, 86, 87, 91, 146, 142, 143, 147, 41, 6, 7, 59, 58, 93, 92, 96, 97, 83, 82, 148, 149, 41, 7, 33, 60, 59, 92, 100, 101, 96, 82, 150, 151, 148, 41, 34, 6, 58, 61, 102, 93, 97, 103, 152, 83, 149, 153, 41, 33, 15, 62, 60, 100, 104, 105, 101, 150, 154, 155, 151, 41, 15, 14, 63, 62, 104, 106, 107, 105, 154, 156, 157, 155, 41, 14, 34, 61, 63, 106, 102, 103, 107, 156, 152, 153, 157, 41, 52, 53, 65, 64, 108, 109, 110, 111, 158, 159, 160, 161, 41, 53, 54, 66, 65, 112, 113, 114, 115, 162, 163, 164, 165, 41, 55, 52, 64, 67, 118, 119, 120, 121, 166, 167, 168, 169, 41, 54, 56, 68, 66, 113, 116, 117, 114, 163, 170, 171, 164, 41, 56, 57, 69, 68, 124, 125, 126, 127, 172, 173, 174, 175, 41, 57, 55, 67, 69, 122, 118, 121, 123, 176, 166, 169, 177, 41, 58, 59, 71, 70, 128, 129, 130, 131, 178, 179, 180, 181, 41, 59, 60, 72, 71, 132, 133, 134, 135, 182, 183, 184, 185, 41, 61, 58, 70, 73, 138, 139, 140, 141, 186, 187, 188, 189, 41, 60, 62, 74, 72, 133, 136, 137, 134, 183, 190, 191, 184, 41, 62, 63, 75, 74, 144, 145, 146, 147, 192, 193, 194, 195, 41, 63, 61, 73, 75, 142, 138, 141, 143, 196, 186, 189, 197, 41, 64, 65, 77, 76, 148, 149, 150, 151, 198, 199, 200, 201, 41, 65, 66, 78, 77, 149, 152, 153, 150, 199, 202, 203, 200, 41, 67, 64, 76, 79, 156, 148, 151, 157, 204, 198, 201, 205, 41, 66, 68, 80, 78, 152, 158, 159, 153, 202, 206, 207, 203, 41, 68, 69, 81, 80, 158, 160, 161, 159, 206, 208, 209, 207, 41, 69, 67, 79, 81, 160, 156, 157, 161, 208, 204, 205, 209, 41, 70, 71, 83, 82, 162, 163, 164, 165, 210, 211, 212, 213, 41, 71, 72, 84, 83, 163, 166, 167, 164, 211, 214, 215, 212, 41, 73, 70, 82, 85, 170, 162, 165, 171, 216, 210, 213, 217, 41, 72, 74, 86, 84, 166, 172, 173, 167, 214, 218, 219, 215, 41, 74, 75, 87, 86, 172, 174, 175, 173, 218, 220, 221, 219, 41, 75, 73, 85, 87, 174, 170, 171, 175, 220, 216, 217, 221, 41, 100, 101, 102, 103, 176, 177, 178, 179, 222, 223, 224, 225, 41, 77, 78, 90, 89, 180, 181, 182, 183, 226, 227, 228, 229, 41, 79, 76, 88, 91, 188, 189, 190, 191, 230, 231, 232, 233, 41, 78, 80, 92, 90, 181, 184, 185, 182, 227, 234, 235, 228, 41, 80, 81, 93, 92, 196, 197, 198, 199, 236, 237, 238, 239, 41, 81, 79, 91, 93, 194, 188, 191, 195, 240, 230, 233, 241, 41, 104, 105, 106, 107, 200, 201, 202, 203, 242, 243, 244, 245, 41, 83, 84, 96, 95, 204, 205, 206, 207, 246, 247, 248, 249, 41, 85, 82, 94, 97, 212, 213, 214, 215, 250, 251, 252, 253, 41, 84, 86, 98, 96, 205, 208, 209, 206, 247, 254, 255, 248, 41, 86, 87, 99, 98, 220, 221, 222, 223, 256, 257, 258, 259, 41, 87, 85, 97, 99, 218, 212, 215, 219, 260, 250, 253, 261, 41, 76, 77, 101, 100, 151, 150, 154, 155, 201, 200, 262, 263, 41, 77, 89, 102, 101, 180, 183, 186, 187, 226, 229, 264, 265, 41, 89, 88, 103, 102, 25, 24, 28, 29, 9, 8, 266, 267, 41, 88, 76, 100, 103, 190, 189, 192, 193, 232, 231, 268, 269, 41, 82, 83, 105, 104, 165, 164, 168, 169, 213, 212, 270, 271, 41, 83, 95, 106, 105, 204, 207, 210, 211, 246, 249, 272, 273, 41, 95, 94, 107, 106, 57, 56, 60, 61, 25, 24, 274, 275, 41, 94, 82, 104, 107, 214, 213, 216, 217, 252, 251, 276, 277, 41, 25, 24, 31, 26, 224, 225, 226, 227, 278, 279, 280, 281, 41, 23, 18, 19, 22, 66, 65, 68, 69, 66, 65, 282, 283, 41, 22, 19, 20, 21, 69, 68, 72, 73, 283, 282, 284, 285, 41, 27, 30, 29, 28, 229, 228, 230, 231, 286, 287, 288, 289, 41, 26, 31, 30, 27, 227, 226, 228, 229, 281, 280, 287, 286],
        "vertices": [1.67042317, 4.03275896, -4.36502924, -1.67042395, 4.03275948, -4.36502924, -4.03276001, 1.67042382, -4.36502924, -4.03275844, -1.67042317, -4.36502924, -1.67042382, -4.03276001, -4.36502924, 1.6704233, -4.0327587, -4.36502924, 4.03276105, -1.67042395, -4.36502924, 4.03275896, 1.67042356, -4.36502924, 1.67042382, 4.03276001, 4.36502924, -1.67042317, 4.03275844, 4.36502924, -4.03276001, 1.67042382, 4.36502924, -4.03275844, -1.67042317, 4.36502924, -1.67042382, -4.03276001, 4.36502924, 1.6704233, -4.0327587, 4.36502924, 4.03276105, -1.67042395, 4.36502924, 4.03275896, 1.67042356, 4.36502924, 0.94699426, 2.2171378, 6.83047695, -0.94699446, 2.21713858, 6.83047695, -2.2862468, 0.91836833, 6.83047695, -2.2862468, -0.91836839, 6.83047695, -0.94699446, -2.21713858, 6.83047695, 0.94699433, -2.21713728, 6.83047695, 2.28624732, -0.91836891, 6.83047695, 2.28624758, 0.91836891, 6.83047695, 0.89561503, 2.15673196, -15.20470413, -0.89561483, 2.15673196, -15.20470413, -2.16220502, 0.89334727, -15.20470413, -2.16220489, -0.89334727, -15.20470413, -0.89561425, -2.15673117, -15.20470413, 0.89561509, -2.15673222, -15.20470413, 2.16220515, -0.89334733, -15.20470413, 2.1622058, 0.89334766, -15.20470413, 1.67042317, 4.03275896, 1.86296253, 4.03275896, 1.67042356, 0.0, 4.03276105, -1.67042395, 0.0, 1.6704233, -4.0327587, 0.0, -1.67042382, -4.03276001, -0.0, -4.03275844, -1.67042317, -0.0, -4.03276001, 1.67042382, -0.0, -1.67042395, 4.03275948, 1.86296253, 1.28301848, 3.09474637, -9.78486616, -1.28301952, 3.09474637, -9.78486616, -3.0974829, 1.28188567, -9.78486616, -3.09748108, -1.28188567, -9.78486616, -1.28301874, -3.09474611, -9.78486616, 1.28301939, -3.09474637, -9.78486616, 3.09748342, -1.28188541, -9.78486616, 3.09748368, 1.28188567, -9.78486616, 0.77727793, 5.34595995, -4.28712837, -0.7772791, 5.34596255, -4.28712837, -0.81640073, 5.37902884, 0.59514022, 0.81640008, 5.37902884, 0.59514035, -4.03276001, 0.75540272, -3.1694965, -4.03275896, -0.75540298, -3.1694965, -4.03275896, -0.75540298, 0.0, -4.03276001, 0.75540272, 0.0, -4.03275896, -0.75540298, 3.1694965, -4.03276001, 0.75540272, 3.1694965, 4.03276105, -0.75540285, -3.1694965, 4.03276053, 0.75540318, -3.1694965, 4.03276053, 0.75540318, 0.0, 4.03276105, -0.75540285, 0.0, 4.03276053, 0.75540318, 3.1694965, 4.03276105, -0.75540285, 3.1694965, -10.53389522, 0.75539869, -1.73042744, -10.53389834, -0.75540598, -1.73042744, -10.53389834, -0.75540598, 0.0, -10.53389522, 0.75539869, 0.0, -10.53389834, -0.75540598, 1.73042744, -10.53389522, 0.75539869, 1.73042744, 10.5338973, -0.75539791, -1.73042757, 10.53389834, 0.75540598, -1.73042757, 10.53389834, 0.75540598, 0.0, 10.5338973, -0.75539791, 0.0, 10.53389834, 0.75540598, 1.73042757, 10.5338973, -0.75539791, 1.73042757, -10.53389626, 1.74228327, -3.78579078, -10.53389522, -1.74228977, -3.78579078, -10.53389522, -1.74228977, 0.0, -10.53389626, 1.74228327, 0.0, -10.53389522, -1.74228977, 3.78579078, -10.53389626, 1.74228327, 3.78579078, 10.53389626, -1.74228327, -3.78579104, 10.53389314, 1.74228977, -3.78579104, 10.53389314, 1.74228977, 0.0, 10.53389626, -1.74228327, 0.0, 10.53389314, 1.74228977, 3.78579104, 10.53389626, -1.74228327, 3.78579104, -13.77626911, 1.74228171, -3.78579078, -13.77626703, -1.74229133, -3.78579078, -13.77626703, -1.74229133, 0.0, -13.77626911, 1.74228171, 0.0, -13.77626703, -1.74229133, 3.78579078, -13.77626911, 1.74228171, 3.78579078, 13.77626911, -1.7422765, -3.78579104, 13.7762639, 1.74229472, -3.78579104, 13.7762639, 1.74229472, 0.0, 13.77626911, -1.7422765, 0.0, 13.7762639, 1.74229472, 3.78579104, 13.77626911, -1.7422765, 3.78579104, -11.49039488, 0.71433355, -7.4676605, -11.49039488, -0.71434109, -7.4676605, -12.81976632, -0.71434213, -7.4676605, -12.81976736, 0.71433303, -7.4676605, 11.49039592, -0.71433199, -7.4676605, 11.4903928, 0.71434213, -7.4676605, 12.81976528, 0.71434396, -7.4676605, 12.81976736, -0.71432991, -7.4676605],
        "normals": [6.7e-07, 0.97012001, -0.24262564, 6.7e-07, 0.97012007, -0.24262556, 8.2e-07, 0.99997711, -0.0067728, 8.2e-07, 0.99997699, -0.0067728, -0.70478702, 0.70491242, -0.07983695, -0.70478618, 0.70491159, -0.07985092, -0.70710677, 0.70710683, 6e-08, -0.70710665, 0.70710683, 1.3e-07, -0.99557716, -8e-07, -0.09394732, -0.99557716, -8e-07, -0.09394733, -1.0, -6.9e-07, 0.0, -1.0, -6.9e-07, 0.0, -0.70428789, -0.70442569, -0.08810792, -0.70428884, -0.70442653, -0.08809391, -0.70710707, -0.70710647, 0.0, -0.70710707, -0.70710647, 0.0, 3e-07, -0.99609917, -0.08823975, 3e-07, -0.99609923, -0.08823976, 3.9e-07, -1.0, 0.0, 3.9e-07, -1.0, 0.0, 0.70428818, -0.70442724, -0.08809389, 0.70428717, -0.70442629, -0.08810788, 0.70710635, -0.70710719, 0.0, 0.70710635, -0.70710719, 0.0, 0.9955771, 1.42e-06, -0.09394721, 0.99557728, 1.42e-06, -0.09394721, 1.0, 1.38e-06, 0.0, 1.0, 1.38e-06, 0.0, 0.704786, 0.70491171, -0.07985087, 0.70478684, 0.70491254, -0.07983689, 0.70710677, 0.70710689, -1.4e-07, 0.70710665, 0.70710689, -6e-08, 0.0, 0.80521572, 0.59298211, 0.0, 0.80521566, 0.59298211, 0.0, 0.80521572, 0.59298205, 0.0, 0.80521566, 0.59298205, -0.57000715, 0.57631028, 0.5856263, -0.57000715, 0.57631034, 0.5856263, -0.57000721, 0.57631034, 0.58562636, -0.57000715, 0.57631022, 0.5856263, -0.81600052, -2.2e-07, 0.57805121, -0.81600046, -2.2e-07, 0.57805115, -0.81600046, -2.2e-07, 0.57805115, -0.81600046, -2.2e-07, 0.57805115, -0.5700075, -0.57630998, 0.58562642, -0.5700075, -0.57630998, 0.58562636, -0.5700075, -0.57630992, 0.5856263, -0.5700075, -0.57631004, 0.58562642, 4.3e-07, -0.80521542, 0.59298223, 4.3e-07, -0.80521554, 0.59298235, 4.3e-07, -0.80521554, 0.59298235, 4.3e-07, -0.80521548, 0.59298235, 0.57000673, -0.57631052, 0.5856266, 0.57000679, -0.57631046, 0.5856266, 0.57000679, -0.57631052, 0.5856266, 0.57000667, -0.57631046, 0.5856266, 0.8160004, 3.6e-07, 0.57805127, 0.81600052, 3.6e-07, 0.57805127, 0.8160004, 3.6e-07, 0.57805121, 0.8160004, 3.6e-07, 0.57805121, 0.57000726, 0.57631016, 0.58562648, 0.57000721, 0.57631016, 0.58562654, 0.57000721, 0.5763101, 0.58562648, 0.57000721, 0.5763101, 0.58562648, 8e-08, 0.0, 1.0, 1.2e-07, 0.0, 1.0, 1.2e-07, 0.0, 1.0, 8e-08, 0.0, 1.0, 5.6e-07, 0.92542064, -0.37894154, 5.6e-07, 0.92542058, -0.37894154, -0.69647926, 0.69707721, -0.17029381, -0.69647926, 0.69707727, -0.17029382, -0.98989505, -5.5e-07, -0.14180169, -0.98989516, -5e-07, -0.14180169, -0.98543501, -5.3e-07, -0.17005213, -0.98543507, -5.3e-07, -0.17005214, -0.69647944, -0.69707704, -0.17029382, -0.69647944, -0.69707698, -0.17029382, 1e-08, -0.98535162, -0.17053528, 1e-08, -0.9853515, -0.17053528, 0.6964792, -0.69707739, -0.17029384, 0.69647908, -0.69707739, -0.17029384, 0.98989505, 4.1e-07, -0.14180163, 0.98989511, 2.6e-07, -0.14180163, 0.98543507, 1.3e-07, -0.17005213, 0.98543507, 1.3e-07, -0.17005213, 0.69647908, 0.69707745, -0.17029372, 0.69647914, 0.69707745, -0.17029372, 0.70710677, 0.70710677, -2.5e-07, 0.70710677, 0.70710677, -2.5e-07, 1.0, 1.38e-06, 0.0, 1.0, 1.38e-06, 0.0, 0.70710635, -0.70710719, 0.0, 0.70710635, -0.70710719, 0.0, 3.9e-07, -1.0, 0.0, 3.9e-07, -1.0, 0.0, -0.70710707, -0.70710647, 0.0, -0.70710707, -0.70710647, 0.0, -1.0, -6.9e-07, 0.0, -1.0, -6.9e-07, 0.0, -0.70710659, 0.70710695, 2.2e-07, -0.70710659, 0.70710695, 2.2e-07, -1.6e-07, 1.0, 4e-08, -1.6e-07, 1.0, 4e-08, -1.6e-07, 1.0, 4e-08, -1.6e-07, 1.0, 4e-08, 0.0, 0.98535156, -0.17053531, 0.0, 0.9853515, -0.17053531, 0.0, 0.98535162, -0.17053531, 0.0, 0.98535162, -0.17053534, -0.69623393, 0.69732225, -0.17029394, -0.69623387, 0.69732219, -0.17029393, -0.98543507, -4.7e-07, -0.17005213, -0.98543507, -4.7e-07, -0.17005213, -0.69623399, -0.69732225, -0.17029387, -0.69623399, -0.69732225, -0.17029387, -2.8e-07, -0.98535162, -0.17053537, -2.8e-07, -0.98535162, -0.17053537, 0.69623393, -0.69732225, -0.17029397, 0.69623387, -0.69732219, -0.17029396, 0.98543501, -9e-08, -0.17005229, 0.98543501, -9e-08, -0.17005226, 0.69623369, 0.69732243, -0.1702939, 0.69623369, 0.69732255, -0.17029391, -0.83032686, 0.55419791, -0.05849712, -0.83670509, 0.54763466, -0.0045761, -0.83670503, 0.54763466, -0.0045761, -0.83232862, 0.55255836, -0.04368601, 3e-08, 0.68557835, 0.72799885, 3e-08, 0.68557835, 0.72799885, 3e-08, 0.68557829, 0.72799897, 3e-08, 0.68557829, 0.72799897, 0.83670491, 0.54763484, -0.00457626, 0.83032662, 0.55419832, -0.05849725, 0.83232838, 0.5525586, -0.04368616, 0.83670497, 0.54763484, -0.00457626, 0.81253374, 0.56184107, -0.15531714, -0.81253433, 0.56184018, -0.15531701, -1.0, -5.4e-07, -9e-08, -1.0, -1.7e-07, -9e-08, -1.0, -6.6e-07, 0.0, -1.0, -6.6e-07, 0.0, -1.0, -0.0, 0.0, -1.0, -0.0, 0.0, -1.0, -5.1e-07, 1.2e-07, -1.0, -5.4e-07, 9e-08, -1.0, -2.1e-07, 1.2e-07, -1.0, -1.7e-07, 9e-08, 1.0, 1.19e-06, -2.8e-07, 1.0, 6e-08, -2.8e-07, 1.0, 1.65e-06, 0.0, 1.0, 1.65e-06, 0.0, 1.0, -2.5e-07, 0.0, 1.0, -2.5e-07, 0.0, 1.0, 1.07e-06, 3.5e-07, 1.0, 1.19e-06, 2.8e-07, 1.0, 2.4e-07, 3.5e-07, 1.0, 1.6e-07, 2.8e-07, -0.21612491, 1.1e-07, -0.9763658, -0.21612491, 1.1e-07, -0.97636575, -0.21612491, 1.1e-07, -0.9763658, -0.21612488, 1.1e-07, -0.97636569, 4.6e-07, -1.0, 0.0, 4.6e-07, -1.0, 0.0, 4.6e-07, -1.0, 0.0, 4.6e-07, -1.0, 0.0, -6.2e-07, 1.0, 0.0, -6.2e-07, 1.0, 0.0, -6.2e-07, 0.99999994, 0.0, -6.2e-07, 1.0, 0.0, 4.6e-07, -1.0, 0.0, 4.6e-07, -1.0, 0.0, -0.21612494, 1.1e-07, 0.97636575, -0.21612495, 1.1e-07, 0.9763658, -0.21612492, 1.1e-07, 0.97636569, -0.21612492, 1.1e-07, 0.97636575, -6.2e-07, 1.0, 0.0, -6.2e-07, 0.99999994, 0.0, 0.21612486, -1.1e-07, -0.97636575, 0.21612485, -1.1e-07, -0.97636575, 0.21612485, -1.1e-07, -0.97636575, 0.21612485, -1.1e-07, -0.97636575, -4.3e-07, 1.0, 0.0, -4.3e-07, 1.0, 0.0, -4.3e-07, 1.0, 0.0, -4.3e-07, 1.0, 0.0, 7.6e-07, -1.0, 0.0, 7.6e-07, -1.0, 0.0, 7.6e-07, -0.99999994, 0.0, 7.6e-07, -1.0, 0.0, -4.3e-07, 1.0, 0.0, -4.3e-07, 1.0, 0.0, 0.21612485, -1.1e-07, 0.97636569, 0.21612488, -1.1e-07, 0.97636575, 0.21612485, -1.1e-07, 0.97636575, 0.21612485, -1.1e-07, 0.97636575, 7.6e-07, -1.0, 0.0, 7.6e-07, -0.99999994, 0.0, 1.0, 6.9e-07, 3e-07, 0.99999994, 1.38e-06, 3e-07, 0.98692763, 2.1e-07, -0.16116452, 0.98692757, 1.1e-07, -0.16116451, 1.0, 3.34e-06, 0.0, 1.0, 3.34e-06, 0.0, 1.0, 1.25e-06, 0.0, 1.0, 1.25e-06, 0.0, 1.0, 1.38e-06, -3e-07, 1.0, 5.8e-07, -4.2e-07, 0.99999994, 3.5e-07, -3e-07, 1.0, 1.5e-07, -4.2e-07, -1.0, 6.9e-07, 8.9e-07, -1.0, -2.07e-06, 8.9e-07, -0.98692757, -9.4e-07, -0.16116431, -0.98692769, -5.2e-07, -0.16116431, -1.0, -5.01e-06, 0.0, -1.0, -5.01e-06, 0.0, -0.99999994, 1.25e-06, 0.0, -0.99999994, 1.25e-06, 0.0, -1.0, -2.07e-06, -8.9e-07, -1.0, -8.7e-07, -1.25e-06, -1.0, 3.5e-07, -8.9e-07, -1.0, 1.5e-07, -1.25e-06, -3.5e-07, 0.0, -0.99999994, -3.5e-07, 0.0, -1.0, -3.5e-07, 0.0, -1.0, -3.5e-07, 0.0, -1.0, 5.2e-07, -0.99480468, -0.10180275, 4.8e-07, -1.0, 0.0, 4.8e-07, -1.0, 0.0, 5.2e-07, -0.99480456, -0.10180271, -4.8e-07, 1.0, 0.0, -4.8e-07, 0.99480462, -0.10180279, -4.8e-07, 0.99480456, -0.10180277, -4.8e-07, 1.0, 0.0, 4.8e-07, -1.0, 0.0, 4.8e-07, -1.0, 0.0, -2e-08, 0.0, 0.99999994, -2e-08, 0.0, 1.0, -2e-08, 0.0, 1.0, -2e-08, 0.0, 0.99999994, -4.8e-07, 1.0, 0.0, -4.8e-07, 1.0, 0.0, -4.1e-07, 0.0, -1.0, -4.1e-07, 0.0, -1.0, -4.1e-07, 0.0, -1.0, -4.1e-07, 0.0, -1.0, -1.5e-06, 0.99480456, -0.1018028, -1.52e-06, 1.0, 0.0, -1.52e-06, 1.0, 0.0, -1.5e-06, 0.99480462, -0.10180277, 2.09e-06, -1.0, 0.0, 2e-06, -0.99480456, -0.10180269, 2e-06, -0.99480462, -0.10180271, 2.09e-06, -1.0, 0.0, -1.52e-06, 1.0, 0.0, -1.52e-06, 1.0, 0.0, -5e-08, 0.0, 1.0, -5e-08, 0.0, 1.0, -5e-08, 0.0, 1.0, -5e-08, 0.0, 1.0, 2.09e-06, -1.0, 0.0, 2.09e-06, -1.0, 0.0, 0.96787292, 0.0, -0.25144008, 0.96787292, 0.0, -0.25144008, 5.8e-07, -0.96316576, -0.26890826, 5.8e-07, -0.96316582, -0.26890829, -0.96787274, -9.7e-07, -0.25144055, -0.9678728, -9.7e-07, -0.25144058, -4.5e-07, 0.96316582, -0.26890826, -4.5e-07, 0.96316576, -0.26890826, -0.96787274, -9.7e-07, -0.2514402, -0.9678728, -9.7e-07, -0.2514402, -1.43e-06, 0.96316576, -0.26890838, -1.43e-06, 0.96316576, -0.26890838, 0.96787274, 1.46e-06, -0.25144032, 0.96787286, 1.46e-06, -0.25144032, 1.82e-06, -0.96316582, -0.26890829, 1.82e-06, -0.96316576, -0.26890823, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, -2.4e-07, 0.0, -0.99999994, -2.4e-07, 0.0, -1.0, 1.1e-07, 0.0, 0.99999994, 1.1e-07, 0.0, 0.99999994, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, -1.2e-07, 0.0, -1.0, -1.2e-07, 0.0, -1.0, 5.9e-07, 0.0, -1.0, 5.9e-07, 0.0, -1.0]
    }

    const RGB = {
        fragPars: '#define RGB( r, g, b ) vec3( float( r ) / 255.0, float( g ) / 255.0, float( b ) / 255.0 )',
    };

    const spaceshipShader = {
        vertexShader: `
    varying vec2 vUv;
    varying vec3 vPosition;

    void main() {
      vUv = uv;
      vPosition = position;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
  `,
        fragmentShader: `
    precision mediump float;

    ${RGB.fragPars}

    varying vec2 vUv;
    varying vec3 vPosition;

    void main() {
      vec4 color1 = vec4(RGB(255, 0, 255), 0.0);
      vec4 color2 = vec4(RGB(0, 255, 255), 0.0);
      // if (vUv.y > .7) {
      //   color = vec4(RGB(0, 255, 255), 0.0);
      // }
      gl_FragColor = mix(color1, color2, vPosition.y / 10. + .5);
    }
  `,
        wireframe: true,
    };

    const treeShader = {
        uniforms: THREE.UniformsLib.fog,
        vertexShader: `
    uniform vec3 mvPosition;
    varying vec2 vUv;

    varying float fogDepth;

    void main() {
      fogDepth = -mvPosition.z;
      vUv = uv;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
  `,
        fragmentShader: `
    precision mediump float;

    ${THREE.ShaderChunk.fog_pars_fragment}

    varying vec2 vUv;

    void main() {
      vec4 color = vec4(.0, 1. - (vUv.y * 1.6), 1. - (vUv.y * .8), 1.); // 1. - vUv.y * 2.
      gl_FragColor = color;

      #ifdef USE_FOG
        #ifdef USE_LOGDEPTHBUF_EXT
          float depth = gl_FragDepthEXT / gl_FragCoord.w;
        #else
          float depth = gl_FragCoord.z / gl_FragCoord.w;
        #endif
        float fogFactor = smoothstep(fogNear, fogFar, depth);
        gl_FragColor.a = gl_FragColor.a * (1. - fogFactor);
      #endif
    }
  `,
        fog: true,
        transparent: true,
    };

    const backgroundShader = {
        uniforms: {},
        vertexShader: `
    attribute vec3 position;

    uniform mat4 modelViewMatrix;
    uniform mat4 projectionMatrix;

    varying vec2 vUv;

    void main() {
      gl_Position = vec4(position, 1.0);
      vUv = vec2(position.x, position.y) * 0.5 + 0.5;
    }
  `,
        fragmentShader: `
    precision mediump float;

    ${RGB.fragPars}

    varying vec2 vUv;

    float lmap(in float val, in float inMin, in float inMax, in float outMin, in float outMax) {
      return clamp(outMin + ((outMax - outMin) * (val - inMin)) / (inMax - inMin), outMin, outMax);
    }

    // gradient with multiple colors in non-equal intervals
    vec3 getColor(in float perc) {
      vec3 uColors[4];
      float uStops[4];
      const int uNumColors = 4;

      uStops[0] = 0.0;
      uStops[1] = 0.28;
      uStops[2] = 0.58;
      uStops[3] = 1.0;

      uColors[0] = RGB(255, 146, 48);
      uColors[1] = RGB(202, 84, 194);
      uColors[2] = RGB(36, 16, 142);
      uColors[3] = RGB(2, 0, 36);

      for (int i = 1; i < uNumColors; i ++) {
          if (perc < uStops[i]) {
              float stopPct = lmap(perc, uStops[i-1], uStops[i], 0.0, 1.0);
              return mix(uColors[i-1], uColors[i], stopPct);
          }
      }
      // edge case, in case the last stop is not at 1.0
      return uColors[uNumColors - 1];
    }

    float blendColorDodge(float base, float blend) {
      return (blend==1.0)?blend:min(base/(1.0-blend),1.0);
    }

    vec3 blendColorDodge(vec3 base, vec3 blend) {
      return vec3(blendColorDodge(base.r,blend.r), blendColorDodge(base.g,blend.g), blendColorDodge(base.b,blend.b));
    }

    vec3 blendColorDodge(vec3 base, vec3 blend, float opacity) {
      return blendColorDodge(base, blend) * opacity + base * (1.0 - opacity);
    }

    vec3 radialGradient(vec2 center, float radius) {
      float distance = length( center - vUv.xy );

      float maxDistance = radius;//pow( radius, 0.23);
      float quadDistance = distance;//pow( distance, 0.23);

      float quadIntensity = 1.0 - min( quadDistance, maxDistance )/maxDistance;

      return vec3(quadIntensity);
    }

    void main() {

      float y = vUv.y * 1.1 - .25;
      vec3 color = RGB(140, 0, 255) * y; // vec3(0.0, y, y); //vec3(0.0, y, y);

      if (vUv.y > .5) {
        vec3 sunset = getColor((vUv.y - .5) * 2.);
        vec3 light = radialGradient(vec2(.5,.2), .8);
        color = blendColorDodge(sunset, light);
      }

      gl_FragColor = vec4(color, 1.0);
    }
  `,
        side: THREE.DoubleSide,
        depthTest: false,
    };

    const keys = {
        W: 1 << 0,
        A: 1 << 1,
        S: 1 << 2,
        D: 1 << 3,
        SPACE: 1 << 4,
        ENTER: 1 << 5,
        ESC: 1 << 6,
        SHIFT: 1 << 7,
        CTRL: 1 << 8,
        LEFT: 1 << 9,
        UP: 1 << 10,
        RIGHT: 1 << 11,
        DOWN: 1 << 12,
    };

    const keyCodes = {
        87: keys.W,
        65: keys.A,
        83: keys.S,
        68: keys.D,
        32: keys.SPACE,
        13: keys.ENTER,
        27: keys.ESC,
        16: keys.SHIFT,
        17: keys.CTRL,
        37: keys.LEFT,
        38: keys.UP,
        39: keys.RIGHT,
        40: keys.DOWN,
    };

    let keysPressed = 0;

    const isKeyDown = keyFlag => Boolean(keysPressed & keyFlag);

    const onKeyDown = ({ keyCode }) => {
        const keyFlag = keyCodes[keyCode];
        keysPressed |= keyFlag;
    };

    const onKeyUp = ({ keyCode }) => {
        keysPressed &= ~keyCodes[keyCode];
    };

    window.addEventListener('keyup', onKeyUp);
    window.addEventListener('keydown', onKeyDown);

    const addUniformsToShader = (shader, uniforms) => ({ ...shader, uniforms: { ...shader.uniforms, ...uniforms } });

    const random = (min, max, round = false) => {
        const num = (Math.random() * (max - min)) + min;
        return round ? Math.floor(num + 1) : num;
    }


    let scene, camera, renderer;
    let playerGeometry, playerMaterial, player;
    let backgroundGeometry, backgroundMaterial, background;

    let time = performance.now();
    let timePlaying = 0;

    const trees = [];
    const treeCount = 500;
    const treeHeight = 100;
    let treePlaceInterval;
    let treePlaceLastTime = time;

    let score = 0;
    const scoreIncrease = 10;
    const scoreUpdateInterval = 500;
    let scoreUpdateLastTime = time;
    const scoreNodes = document.querySelectorAll('.js-score');

    let speed = 600;
    const speedIncrease = 3;
    let playerSpeed = 0;
    const playerAcceleration = 70;
    const playerMaxSpeed = 700;

    const gameStates = {
        PLAYING: 1,
        GAME_OVER: 2,
    };
    let gameState = gameStates.PLAYING;

    loadAssets();

    function init() {
        scene = new THREE.Scene();
        scene.fog = new THREE.Fog(0xFF00FF, 1100, 2000);

        camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
        camera.position.set(0, 50, 0);

        renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setSize(window.innerWidth, window.innerHeight);

        document.body.appendChild(renderer.domElement);

        window.addEventListener('resize', resize);
        attachDOMListeners();

        createObjects();

        requestAnimationFrame(update);
    }

    function loadAssets() {
        const loader = new THREE.JSONLoader();
        playerGeometry = loader.parse(spaceshipModel).geometry;
        init();
    }

    function reset() {
        hideGameOver();

        while (scene.children.length) {
            scene.remove(scene.children[0]);
        }
        trees.length = 0;
        score = 0;

        createObjects();

        time = performance.now();
        timePlaying = 0;
        gameState = gameStates.PLAYING;
    }

    function createObjects() {
        backgroundGeometry = new THREE.PlaneGeometry(2, 2, 1);
        backgroundMaterial = new THREE.RawShaderMaterial(backgroundShader);
        background = new THREE.Mesh(backgroundGeometry, backgroundMaterial);
        background.frustumCulled = false;
        scene.add(background);

        playerMaterial = new THREE.ShaderMaterial(spaceshipShader);
        player = new THREE.Mesh(playerGeometry, playerMaterial);
        player.position.set(0, 20, -45);
        scene.add(player);

        createTrees();
    }

    function createTrees() {
        const geometry = new THREE.ConeGeometry(12, treeHeight, 4);
        const uniforms = {
            fogColor: { value: scene.fog.color },
            fogNear: { value: scene.fog.near },
            fogFar: { value: scene.fog.far },
        };
        const shader = addUniformsToShader(treeShader, uniforms);
        const material = new THREE.ShaderMaterial(shader);

        for (let i = 0; i < treeCount; i++) {
            const mesh = new THREE.Mesh(geometry, material);
            const scale = random(1, 2);
            mesh.scale.set(1, scale, 1);
            mesh.rotateY(Math.PI * random(0, 0.5));
            mesh.inUse = false;
            mesh.visible = false;
            trees.push(mesh);
            scene.add(mesh);
        }
    }

    function getTree() {
        let tree;
        let i = 0;

        do {
            tree = trees[i];
            i++;
        } while (tree.inUse === true && i < treeCount);

        return tree;
    }

    function placeTree() {
        const tree = getTree();
        const offsetY = (treeHeight * tree.scale.y) / 2;
        tree.inUse = true;
        tree.visible = true;
        tree.position.set(random(camera.position.x - 2500, camera.position.x + 2500), offsetY, -2000);
    }

    function removeTree(i) {
        trees[i].inUse = false;
        trees[i].visible = false;
    }

    function updateTrees(delta) {
        for (let i = 0; i < trees.length; i++) {
            if (!trees[i].inUse === true) continue;
            trees[i].position.z += speed * delta;
            checkCollision(trees[i].position.x, trees[i].position.z);

            if (trees[i].position.z > 10) {
                removeTree(i);
            }
        }

        if (time - treePlaceLastTime >= treePlaceInterval) {
            placeTree();
            treePlaceLastTime = time;
        }
    }

    function updatePlayer(delta) {
        let targetSpeed = 0;

        if (isKeyDown(keys.A) || isKeyDown(keys.LEFT)) {
            targetSpeed = -playerMaxSpeed;
        } else if (isKeyDown(keys.D) || isKeyDown(keys.RIGHT)) {
            targetSpeed = playerMaxSpeed;
        }

        if (playerSpeed < targetSpeed) {
            playerSpeed += playerAcceleration;
        } else if (playerSpeed > targetSpeed) {
            playerSpeed -= playerAcceleration;
        }

        player.position.x += playerSpeed * delta;
        player.rotation.z = -playerSpeed * 0.0006;
        camera.position.x = player.position.x;
        camera.updateProjectionMatrix();
    }

    function checkCollision(x, z) {
        if (Math.abs(player.position.z - z) < 20 && Math.abs(player.position.x - x) < 25) {
            gameState = gameStates.GAME_OVER;
            showGameOver();
        }
    }

    function attachDOMListeners() {
        const nodes = document.querySelectorAll('.js-play');
        Array.prototype.forEach.call(nodes, node => node.addEventListener('click', reset));
    }

    function updateScore() {
        if (time - scoreUpdateLastTime >= scoreUpdateInterval) {
            score += scoreIncrease;
            scoreUpdateLastTime = time;
        }

        Array.prototype.forEach.call(scoreNodes, node => node.innerHTML = score);
    }

    function showGameOver() {
        document.getElementById('gameover').style.visibility = 'visible';
    }

    function hideGameOver() {
        document.getElementById('gameover').style.visibility = 'hidden';
    }

    function resize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
    }

    function update(newTime) {
        requestAnimationFrame(update);

        const delta = (newTime - time) / 1000;
        time = newTime;

        if (delta > 0.5) return;

        renderer.render(scene, camera);

        if (gameState !== gameStates.PLAYING) return;

        timePlaying += delta;
        speed += speedIncrease * delta;
        treePlaceInterval = (1 / speed) * 40 * 1000;

        updateTrees(delta);
        updatePlayer(delta);
        updateScore();
    }

</script>
</body>
</html>